package org.dromara.iot.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.holder.WebSocketSessionHolder;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.iot.domain.IotElevator;
import org.dromara.iot.domain.IotElevatorOss;
import org.dromara.iot.domain.bo.IotElevatorBo;
import org.dromara.iot.domain.vo.IotElevatorVo;
import org.dromara.iot.mapper.IotElevatorMapper;
import org.dromara.iot.mapper.IotElevatorOssMapper;
import org.dromara.iot.service.IIotElevatorService;
import org.dromara.system.domain.SysOss;
import org.dromara.system.domain.vo.SysOssVo;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 电梯管理Service业务层处理
 *
 * @author LSL
 * @date 2024-06-16
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class IotElevatorServiceImpl implements IIotElevatorService {

    private final IotElevatorMapper baseMapper;

    private final IotElevatorOssMapper elevatorOssMapper;

    /**
     * 查询电梯管理
     */
    @Override
    public IotElevatorVo queryById(Long elevatorId) {
        return baseMapper.selectOwnVoById(elevatorId);
    }

    /**
     * 查询电梯管理列表
     */
    @Override
    public TableDataInfo<IotElevatorVo> queryPageList(IotElevatorBo bo, PageQuery pageQuery) {
        QueryWrapper<IotElevator> lqw = Wrappers.query();
        lqw.like(StringUtils.isNotBlank(bo.getElevatorName()), "ie.elevator_name", bo.getElevatorName());
        lqw.eq(StringUtils.isNotBlank(bo.getNumberCode()), "ie.number_code", bo.getNumberCode());
        lqw.eq(bo.getCommunityId() != null, "ie.community_id", bo.getCommunityId());
        Page<IotElevatorVo> result = baseMapper.selectOwnVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询电梯管理列表
     */
    @Override
    public List<IotElevatorVo> queryList(IotElevatorBo bo) {
        LambdaQueryWrapper<IotElevator> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<IotElevator> buildQueryWrapper(IotElevatorBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IotElevator> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getCommunityId() != null, IotElevator::getCommunityId, bo.getCommunityId());
        lqw.like(StringUtils.isNotBlank(bo.getElevatorName()), IotElevator::getElevatorName, bo.getElevatorName());
        lqw.eq(StringUtils.isNotBlank(bo.getNumberCode()), IotElevator::getNumberCode, bo.getNumberCode());
        lqw.eq(StringUtils.isNotBlank(bo.getRegisteredCode()), IotElevator::getRegisteredCode, bo.getRegisteredCode());
        lqw.eq(StringUtils.isNotBlank(bo.getIdentifyCode()), IotElevator::getIdentifyCode, bo.getIdentifyCode());
        lqw.eq(StringUtils.isNotBlank(bo.getElevatorBrand()), IotElevator::getElevatorBrand, bo.getElevatorBrand());
        lqw.eq(StringUtils.isNotBlank(bo.getLayerNum()), IotElevator::getLayerNum, bo.getLayerNum());
        lqw.eq(StringUtils.isNotBlank(bo.getStandingNum()), IotElevator::getStandingNum, bo.getStandingNum());
        lqw.eq(bo.getInstallationDate() != null, IotElevator::getInstallationDate, bo.getInstallationDate());
        lqw.eq(bo.getAnnualDate() != null, IotElevator::getAnnualDate, bo.getAnnualDate());
        lqw.eq(bo.getNextAnnualDate() != null, IotElevator::getNextAnnualDate, bo.getNextAnnualDate());
        lqw.eq(StringUtils.isNotBlank(bo.getUseUnit()), IotElevator::getUseUnit, bo.getUseUnit());
        lqw.eq(StringUtils.isNotBlank(bo.getElevatorAdministrator()), IotElevator::getElevatorAdministrator, bo.getElevatorAdministrator());
        lqw.eq(StringUtils.isNotBlank(bo.getMaintenanceUnit()), IotElevator::getMaintenanceUnit, bo.getMaintenanceUnit());
        lqw.eq(StringUtils.isNotBlank(bo.getMaintenanceEngineer()), IotElevator::getMaintenanceEngineer, bo.getMaintenanceEngineer());
        lqw.eq(StringUtils.isNotBlank(bo.getNetworkStatus()), IotElevator::getNetworkStatus, bo.getNetworkStatus());
        lqw.eq(bo.getNetworkDate() != null, IotElevator::getNetworkDate, bo.getNetworkDate());
        lqw.eq(StringUtils.isNotBlank(bo.getElevatorStatus()), IotElevator::getElevatorStatus, bo.getElevatorStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getCheckFix()), IotElevator::getCheckFix, bo.getCheckFix());
        lqw.eq(bo.getUnitId() != null, IotElevator::getUnitId, bo.getUnitId());
        lqw.eq(bo.getFloorId() != null, IotElevator::getFloorId, bo.getFloorId());
        lqw.eq(StringUtils.isNotBlank(bo.getLongitude()), IotElevator::getLongitude, bo.getLongitude());
        lqw.eq(StringUtils.isNotBlank(bo.getLatitude()), IotElevator::getLatitude, bo.getLatitude());
        lqw.eq(StringUtils.isNotBlank(bo.getUsePlace()), IotElevator::getUsePlace, bo.getUsePlace());
        lqw.eq(StringUtils.isNotBlank(bo.getBuildType()), IotElevator::getBuildType, bo.getBuildType());
        lqw.eq(StringUtils.isNotBlank(bo.getElevatorType()), IotElevator::getElevatorType, bo.getElevatorType());
        lqw.eq(StringUtils.isNotBlank(bo.getStraightElevatorType()), IotElevator::getStraightElevatorType, bo.getStraightElevatorType());
        lqw.eq(StringUtils.isNotBlank(bo.getEscalatorType()), IotElevator::getEscalatorType, bo.getEscalatorType());
        lqw.eq(StringUtils.isNotBlank(bo.getVendor()), IotElevator::getVendor, bo.getVendor());
        lqw.eq(bo.getProductionDate() != null, IotElevator::getProductionDate, bo.getProductionDate());
        lqw.eq(StringUtils.isNotBlank(bo.getUseType()), IotElevator::getUseType, bo.getUseType());
        lqw.eq(StringUtils.isNotBlank(bo.getRatedLoad()), IotElevator::getRatedLoad, bo.getRatedLoad());
        lqw.eq(StringUtils.isNotBlank(bo.getBumperType()), IotElevator::getBumperType, bo.getBumperType());
        lqw.eq(StringUtils.isNotBlank(bo.getModelNumber()), IotElevator::getModelNumber, bo.getModelNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getFactoryCode()), IotElevator::getFactoryCode, bo.getFactoryCode());
        lqw.eq(StringUtils.isNotBlank(bo.getNominal()), IotElevator::getNominal, bo.getNominal());
        lqw.eq(StringUtils.isNotBlank(bo.getInstallUnit()), IotElevator::getInstallUnit, bo.getInstallUnit());
        lqw.eq(StringUtils.isNotBlank(bo.getPromoteHeight()), IotElevator::getPromoteHeight, bo.getPromoteHeight());
        lqw.eq(StringUtils.isNotBlank(bo.getTractorPower()), IotElevator::getTractorPower, bo.getTractorPower());
        lqw.eq(StringUtils.isNotBlank(bo.getStandardFloorHeight()), IotElevator::getStandardFloorHeight, bo.getStandardFloorHeight());
        lqw.eq(StringUtils.isNotBlank(bo.getSpecialEquipmentCode()), IotElevator::getSpecialEquipmentCode, bo.getSpecialEquipmentCode());
        lqw.eq(bo.getIssueDate() != null, IotElevator::getIssueDate, bo.getIssueDate());
        lqw.eq(StringUtils.isNotBlank(bo.getSpecialEquipmentRegistration()), IotElevator::getSpecialEquipmentRegistration, bo.getSpecialEquipmentRegistration());
        lqw.eq(StringUtils.isNotBlank(bo.getInspectionReportNum()), IotElevator::getInspectionReportNum, bo.getInspectionReportNum());
        lqw.eq(StringUtils.isNotBlank(bo.getInspectionReport()), IotElevator::getInspectionReport, bo.getInspectionReport());
        lqw.eq(StringUtils.isNotBlank(bo.getSpecialEquipmentUseFlag()), IotElevator::getSpecialEquipmentUseFlag, bo.getSpecialEquipmentUseFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getApprovalNumber()), IotElevator::getApprovalNumber, bo.getApprovalNumber());
        lqw.like(StringUtils.isNotBlank(bo.getApprovalName()), IotElevator::getApprovalName, bo.getApprovalName());
        lqw.eq(StringUtils.isNotBlank(bo.getApprovalType()), IotElevator::getApprovalType, bo.getApprovalType());
        lqw.eq(StringUtils.isNotBlank(bo.getApprovalUnit()), IotElevator::getApprovalUnit, bo.getApprovalUnit());
        lqw.eq(bo.getApprovalDate() != null, IotElevator::getApprovalDate, bo.getApprovalDate());
        lqw.eq(bo.getApplicationDate() != null, IotElevator::getApplicationDate, bo.getApplicationDate());
        lqw.eq(StringUtils.isNotBlank(bo.getAuditStatus()), IotElevator::getAuditStatus, bo.getAuditStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getIsFault()), IotElevator::getIsFault, bo.getIsFault());
        lqw.eq(StringUtils.isNotBlank(bo.getShaftHeight()), IotElevator::getShaftHeight, bo.getShaftHeight());
        lqw.eq(StringUtils.isNotBlank(bo.getCurLayer()), IotElevator::getCurLayer, bo.getCurLayer());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), IotElevator::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增电梯管理
     */
    @Override
    public Boolean insertByBo(IotElevatorBo bo) {
        IotElevator add = MapstructUtils.convert(bo, IotElevator.class);
        validEntityBeforeSave(add);
        bo.setElevatorAdministrator(LoginHelper.getLoginUser().getNickname());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setElevatorId(add.getElevatorId());
        }
        return flag;
    }

    /**
     * 修改电梯管理
     */
    @Override
    public Boolean updateByBo(IotElevatorBo bo) {
        IotElevator update = MapstructUtils.convert(bo, IotElevator.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IotElevator entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除电梯管理
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 根据编号获取电梯
     */
    @Override
    public IotElevatorVo selectByRegisteredCode(String registeredCode) {
        LambdaQueryWrapper<IotElevator> lqw = Wrappers.lambdaQuery();
        lqw.eq(IotElevator::getRegisteredCode, registeredCode);
        return baseMapper.selectVoOne(lqw);
    }

    /**
     * 刷新电梯界面
     *
     * @param elevatorId
     */
    @Override
    public Boolean refresh(Long elevatorId) {
        IotElevatorVo iotElevatorVo = this.queryById(elevatorId);
        if (iotElevatorVo == null) {
            throw new RuntimeException("电梯不存在");
        }
        if (!WebSocketSessionHolder.existSession(iotElevatorVo.getRegisteredCode())) {
            throw new RuntimeException("电梯已离线！！！");
        }
        WebSocketMessageDto webSocketMessageDto = new WebSocketMessageDto();
        webSocketMessageDto.setMessage("refresh");
        webSocketMessageDto.setSessionKeys(Collections.singletonList(iotElevatorVo.getRegisteredCode()));
        WebSocketUtils.publishMessage(webSocketMessageDto);
        return true;
    }

    @Override
    public TableDataInfo<SysOssVo> selectAllocatedList(IotElevatorBo bo, PageQuery pageQuery) {
        QueryWrapper<IotElevator> wrapper = Wrappers.query();
        wrapper.eq(ObjectUtil.isNotNull(bo.getElevatorId()), "ieo.elevator_id", bo.getElevatorId());
        wrapper.eq(StringUtils.isNotEmpty(bo.getRegisteredCode()), "ie.registered_code", bo.getRegisteredCode());
        if (ObjectUtil.isNull(bo.getElevatorId()) && StringUtils.isEmpty(bo.getRegisteredCode())) {
            return TableDataInfo.build();
        }
        Page<SysOssVo> page = baseMapper.selectAllocatedList(pageQuery.build(), wrapper);
        return TableDataInfo.build(page);
    }

    @Override
    public TableDataInfo<SysOssVo> selectUnallocatedList(IotElevatorBo bo, PageQuery pageQuery) {
        QueryWrapper<SysOss> wrapper = Wrappers.query();
        // 排除已被当前电梯关联的OSS
        wrapper.notExists(
                "SELECT 1 FROM iot_elevator_oss ieo " +
                        "WHERE ieo.oss_id = so.oss_id AND ieo.elevator_id = {0}",
                bo.getElevatorId()
        );
        // 分页查询
        Page<SysOssVo> page = baseMapper.selectUnallocatedList(pageQuery.build(), wrapper);
        return TableDataInfo.build(page);
    }

    @Override
    public int deleteOss(IotElevatorOss elevatorOss) {
        int rows = elevatorOssMapper.delete(new LambdaQueryWrapper<IotElevatorOss>().eq(IotElevatorOss::getElevatorId, elevatorOss.getElevatorId()).eq(IotElevatorOss::getOssId, elevatorOss.getOssId()));
        if (rows > 0) {
            refresh(elevatorOss.getElevatorId());
        }
        return rows;
    }

    @Override
    public int deleteOssList(Long elevatorId, Long[] ossIds) {
        int rows = elevatorOssMapper.delete(new LambdaQueryWrapper<IotElevatorOss>().eq(IotElevatorOss::getElevatorId, elevatorId).in(IotElevatorOss::getOssId, Arrays.asList(ossIds)));
        if (rows > 0) {
            refresh(elevatorId);
        }
        return rows;
    }

    @Override
    public int insertOssList(Long elevatorId, Long[] ossIds) {
        int rows = 1;
        List<IotElevatorOss> list = StreamUtils.toList(List.of(ossIds), ossId -> {
            IotElevatorOss elevatorOss = new IotElevatorOss();
            elevatorOss.setElevatorId(elevatorId);
            elevatorOss.setOssId(ossId);
            return elevatorOss;
        });
        if (CollUtil.isNotEmpty(list)) {
            rows = elevatorOssMapper.insertBatch(list) ? list.size() : 0;
        }
        if (rows > 0) {
            refresh(elevatorId);
        }
        return rows;
    }

    @Override
    public List<IotElevatorVo> queryByIds(List<Long> elevatorIds) {
        return baseMapper.selectOwnVoByIds(elevatorIds);
    }

    @Override
    public IotElevatorVo selectByIdentifyCode(String identifyCode) {
        LambdaQueryWrapper<IotElevator> lqw = Wrappers.lambdaQuery();
        lqw.eq(IotElevator::getIdentifyCode, identifyCode);
        return baseMapper.selectVoOne(lqw);
    }

}
